package org.aom.service.idstar.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUtils;

import org.aom.entity.security.Authority;
import org.aom.entity.security.Role;
import org.aom.entity.security.User;
import org.aom.service.security.impl.SecurityEntityManager;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.util.Assert;

import com.wiscom.is.IdentityFactory;
import com.wiscom.is.IdentityManager;

/**
 * <p>
 * Title:
 * </p>
 * <p>
 * Description: 从请求中获取客户端存在的cookie，模拟完成单点登陆等功能<br>
 * 具体更多的安全因素则是由cookie存储和读取的规则保证，本类负责验证的时候，完全信赖这种规则<br>
 * 简而言之，如果在request存在一定规则的cookie则信任该用户是登陆的，取得用户信息后，就去数据库完成权限的赋予，继而完成一个spring
 * security能够认出来的凭证
 * </p>
 * <p>
 * Copyright: Copyright (c) 2009
 * </p>
 * <p>
 * Company:ustb
 * </p>
 * 
 * @author: Saya
 * @version: 0.1
 * @time: 2009-11-18
 * 
 */
@SuppressWarnings("deprecation")
public class CustomCookieFilter extends SpringSecurityFilter implements
		InitializingBean {

	@Autowired
	private SecurityEntityManager securityEntityManager;

	// idstar设置在浏览器中的cookie名称
	private final String cookieName = "iPlanetDirectoryPro";

	public static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";

	static final String FILTER_APPLIED = "__spring_security_session_integration_filter_applied";

	// ~ Methods
	// ========================================================================================================

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(this.securityEntityManager,
				"An SecurityEntityManager is required");
	}

	public void doFilterHttp(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//if (SecurityContextHolder.getContext().getAuthentication() == null) {
			String curUser = getUserNameFromCookie(request);
			if (curUser != null) {
				User user = securityEntityManager.findUserByLoginName(curUser);
				if (user != null && user.getEnable() == 1) {
					GrantedAuthority[] grantedAuths = obtainGrantedAuthorities(user);
					org.springframework.security.userdetails.User userdetail = new org.springframework.security.userdetails.User(
							user.getLoginName(), user.getPassword(), true,
							true, true, true, grantedAuths);
					UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
							userdetail, user.getPassword(), grantedAuths);
					authentication.setDetails(grantedAuths);
					SecurityContextHolder.getContext().setAuthentication(
							authentication);
					HttpSession httpSession = safeGetSession(request, true);
					httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY,
							SecurityContextHolder.getContext());
					request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
				}
			} else {
				SecurityContextHolder.getContext().setAuthentication(null);
				HttpSession httpSession = safeGetSession(request, true);
				httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null);
				String gotoURL = HttpUtils.getRequestURL(request).toString();
				String loginURL;
				try {
					loginURL = getIM(request).getLoginURL() + "?goto="
							+ java.net.URLEncoder.encode(gotoURL);
					response.sendRedirect(loginURL);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		//}

		chain.doFilter(request, response);
	}

	private String getUserNameFromCookie(HttpServletRequest request) {
		Cookie all_cookies[] = request.getCookies();
		Cookie myCookie;
		String decodedCookieValue = null;
		if (all_cookies != null) {
			for (int i = 0; i < all_cookies.length; i++) {
				myCookie = all_cookies[i];
				if (myCookie.getName().equals(cookieName)) {
					try {
						decodedCookieValue = URLDecoder.decode(myCookie
								.getValue(), "GB2312");
						String curUser = "";
						if (decodedCookieValue != null) {
							curUser = getIM(request).getCurrentUser(
									decodedCookieValue);
							System.out.println(curUser);
							return curUser;
						}
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return null;
	}

	private IdentityManager getIM(HttpServletRequest request) throws Exception {
		String is_config = request.getRealPath("/client.properties");
		IdentityFactory factory;
		factory = IdentityFactory.createFactory(is_config);
		return factory.getIdentityManager();
	}

	private HttpSession safeGetSession(HttpServletRequest request,
			boolean allowCreate) {
		try {
			return request.getSession(allowCreate);
		} catch (IllegalStateException ignored) {
			return null;
		}
	}

	/**
	 * 获得用户所有角色的权限集合.
	 */
	private GrantedAuthority[] obtainGrantedAuthorities(User user) {
		Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();
		for (Role role : user.getRoleList()) {
			for (Authority authority : role.getAuthorityList()) {
				authSet.add(new GrantedAuthorityImpl(authority.getName()));
			}
		}
		return authSet.toArray(new GrantedAuthority[authSet.size()]);
	}

	public int getOrder() {
		return FilterChainOrder.HTTP_SESSION_CONTEXT_FILTER - 1;
	}

}
